import type { Context } from 'elysia';
import { eq, desc, asc, like, and, count } from 'drizzle-orm';
import { db } from '../db';
import { tags } from '../db/schema';
import { successResponse, errorResponse, ApiError, asyncHandler, Logger } from '../utils/response';
import { nanoid } from 'nanoid';
import { checkReadOnlyAccess } from '../middleware/auth';

// 获取标签列表
export const getTags = asyncHandler(async ({ query }: Context) => {
  try {
    const {
      page = 1,
      limit = 20,
      search,
      type,
      status,
      sortBy = 'createdAt',
      sortOrder = 'desc'
    } = query as any;

    const pageNum = parseInt(page as string);
    const limitNum = parseInt(limit as string);
    const offset = (pageNum - 1) * limitNum;

    // 构建查询条件
    const conditions = [];
    
    if (search) {
      conditions.push(like(tags.name, `%${search}%`));
    }
    
    if (type) {
      conditions.push(eq(tags.type, type));
    }
    
    if (status) {
      conditions.push(eq(tags.status, status));
    }

    const whereClause = conditions.length > 0 ? and(...conditions) : undefined;

    // 排序
    let orderBy;
    switch (sortBy) {
      case 'name':
        orderBy = sortOrder === 'desc' ? desc(tags.name) : asc(tags.name);
        break;
      case 'type':
        orderBy = sortOrder === 'desc' ? desc(tags.type) : asc(tags.type);
        break;
      case 'usageCount':
        orderBy = sortOrder === 'desc' ? desc(tags.usageCount) : asc(tags.usageCount);
        break;
      case 'createdAt':
      default:
        orderBy = sortOrder === 'desc' ? desc(tags.createdAt) : asc(tags.createdAt);
        break;
    }

    // 获取数据和总数
    const [tagList, totalResult] = await Promise.all([
      db.select()
        .from(tags)
        .where(whereClause)
        .orderBy(orderBy)
        .limit(limitNum)
        .offset(offset),
      db.select({ count: count() })
        .from(tags)
        .where(whereClause)
    ]);

    const total = totalResult[0]?.count || 0;
    const totalPages = Math.ceil(total / limitNum);

    Logger.info('标签列表查询成功', {
      total,
      page: pageNum,
      limit: limitNum,
      filters: { search, type, status }
    });

    return successResponse({
      tags: tagList,
      pagination: {
        page: pageNum,
        limit: limitNum,
        total,
        totalPages
      }
    });
  } catch (error) {
    Logger.error('获取标签列表失败', error);
    throw new ApiError('获取标签列表失败', 500);
  }
});

// 获取标签详情
export const getTagById = asyncHandler(async ({ params }: Context) => {
  try {
    const { id } = params as { id: string };

    const tag = await db.select()
      .from(tags)
      .where(eq(tags.id, id))
      .limit(1);

    if (!tag.length) {
      throw new ApiError('标签不存在', 404);
    }

    Logger.info('标签详情查询成功', { tagId: id });
    return successResponse(tag[0]);
  } catch (error) {
    if (error instanceof ApiError) throw error;
    Logger.error('获取标签详情失败', error);
    throw new ApiError('获取标签详情失败', 500);
  }
});

// 创建标签
export const createTag = asyncHandler(async ({ body, user }: Context) => {
  try {
    // 检查权限
    const accessCheck = checkReadOnlyAccess(user, 'POST');
    if (!accessCheck.allowed) {
      throw new ApiError(accessCheck.message, 403);
    }
    const { name, type = 'case', color = '#3B82F6', status = 'active' } = body as any;

    if (!name) {
      throw new ApiError('标签名称不能为空', 400);
    }

    // 检查标签名称是否已存在
    const existingTag = await db.select()
      .from(tags)
      .where(eq(tags.name, name))
      .limit(1);

    if (existingTag.length > 0) {
      throw new ApiError('标签名称已存在', 400);
    }

    const tagId = nanoid();
    const now = new Date().toISOString();

    const newTag = {
      id: tagId,
      name,
      type,
      color,
      status,
      usageCount: 0,
      createdAt: now,
      updatedAt: now
    };

    await db.insert(tags).values(newTag);

    Logger.info('标签创建成功', { tagId, name });
    return successResponse(newTag, '标签创建成功');
  } catch (error) {
    if (error instanceof ApiError) throw error;
    Logger.error('创建标签失败', error);
    throw new ApiError('创建标签失败', 500);
  }
});

// 更新标签
export const updateTag = asyncHandler(async ({ params, body, user }: Context) => {
  try {
    // 检查权限
    const accessCheck = checkReadOnlyAccess(user, 'PUT');
    if (!accessCheck.allowed) {
      throw new ApiError(accessCheck.message, 403);
    }
    const { id } = params as { id: string };
    const { name, type, color, status } = body as any;

    // 检查标签是否存在
    const existingTag = await db.select()
      .from(tags)
      .where(eq(tags.id, id))
      .limit(1);

    if (!existingTag.length) {
      throw new ApiError('标签不存在', 404);
    }

    // 如果更新名称，检查是否与其他标签重复
    if (name && name !== existingTag[0].name) {
      const duplicateTag = await db.select()
        .from(tags)
        .where(eq(tags.name, name))
        .limit(1);

      if (duplicateTag.length > 0) {
        throw new ApiError('标签名称已存在', 400);
      }
    }

    const updateData: any = {
      updatedAt: new Date().toISOString()
    };

    if (name !== undefined) updateData.name = name;
    if (type !== undefined) updateData.type = type;
    if (color !== undefined) updateData.color = color;
    if (status !== undefined) updateData.status = status;

    await db.update(tags)
      .set(updateData)
      .where(eq(tags.id, id));

    // 获取更新后的标签
    const updatedTag = await db.select()
      .from(tags)
      .where(eq(tags.id, id))
      .limit(1);

    Logger.info('标签更新成功', { tagId: id });
    return successResponse(updatedTag[0], '标签更新成功');
  } catch (error) {
    if (error instanceof ApiError) throw error;
    Logger.error('更新标签失败', error);
    throw new ApiError('更新标签失败', 500);
  }
});

// 删除标签
export const deleteTag = asyncHandler(async ({ params, user }: Context) => {
  try {
    // 检查权限
    const accessCheck = checkReadOnlyAccess(user, 'DELETE');
    if (!accessCheck.allowed) {
      throw new ApiError(accessCheck.message, 403);
    }
    const { id } = params as { id: string };

    // 检查标签是否存在
    const existingTag = await db.select()
      .from(tags)
      .where(eq(tags.id, id))
      .limit(1);

    if (!existingTag.length) {
      throw new ApiError('标签不存在', 404);
    }

    await db.delete(tags).where(eq(tags.id, id));

    Logger.info('标签删除成功', { tagId: id });
    return successResponse(null, '标签删除成功');
  } catch (error) {
    if (error instanceof ApiError) throw error;
    Logger.error('删除标签失败', error);
    throw new ApiError('删除标签失败', 500);
  }
});

// 批量删除标签
export const batchDeleteTags = asyncHandler(async ({ body, user }: Context) => {
  try {
    // 检查权限
    const accessCheck = checkReadOnlyAccess(user, 'DELETE');
    if (!accessCheck.allowed) {
      throw new ApiError(accessCheck.message, 403);
    }
    const { ids } = body as { ids: string[] };

    if (!ids || !Array.isArray(ids) || ids.length === 0) {
      throw new ApiError('请选择要删除的标签', 400);
    }

    // 检查标签是否存在
    const existingTags = await db.select()
      .from(tags)
      .where(eq(tags.id, ids[0])); // 简化检查，实际应该检查所有ID

    // 执行批量删除
    for (const id of ids) {
      await db.delete(tags).where(eq(tags.id, id));
    }

    Logger.info('批量删除标签成功', { count: ids.length });
    return successResponse(null, `成功删除 ${ids.length} 个标签`);
  } catch (error) {
    if (error instanceof ApiError) throw error;
    Logger.error('批量删除标签失败', error);
    throw new ApiError('批量删除标签失败', 500);
  }
});

// 获取标签统计
export const getTagStats = asyncHandler(async ({ }: Context) => {
  try {
    const [totalResult, caseTagsResult, productTagsResult, activeResult] = await Promise.all([
      db.select({ count: count() }).from(tags),
      db.select({ count: count() }).from(tags).where(eq(tags.type, 'case')),
      db.select({ count: count() }).from(tags).where(eq(tags.type, 'product')),
      db.select({ count: count() }).from(tags).where(eq(tags.status, 'active'))
    ]);

    const stats = {
      total: totalResult[0]?.count || 0,
      caseTags: caseTagsResult[0]?.count || 0,
      productTags: productTagsResult[0]?.count || 0,
      active: activeResult[0]?.count || 0
    };

    Logger.info('标签统计查询成功', stats);
    return successResponse(stats);
  } catch (error) {
    Logger.error('获取标签统计失败', error);
    throw new ApiError('获取标签统计失败', 500);
  }
});